﻿using AntdUI;
using ImportPlcPointPosition.Controls.Base;
using ImportPlcPointPosition.Core;
using ImportPlcPointPosition.Extensions;
using ImportPlcPointPosition.Forms;
using ImportPlcPointPosition.Models.Table;
using ImportPlcPointPosition.Utils;
using Mapster;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
using S7.Net;
using SqlSugar;
using SqlSugar.Extensions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using ZR.Model.Models.ProductionControl;

namespace ImportPlcPointPosition.Controls {
    public partial class BlockDbTableControl : BasePointConfigContol {
        /// <summary>
        /// 监听显示列
        /// </summary>
        private readonly List<string> ListenShowColumns = new List<string>() { "WatchValue", "WriteValue", "Operate", "AutoWrite" };
        /// <summary>
        /// 监听隐藏列
        /// </summary>
        private readonly List<string> ListenHideColumn = new List<string>() { "IsCheck", "Id", "ParentId" };

        /// <summary>
        /// MesDbClient
        /// </summary>
        private readonly SqlSugarClient MesDbClient = SqlSugarHelper.MesDB;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="plcConfig">plc配置对象</param>
        /// <param name="plcBlockDb">plc数据块对象</param>
        public BlockDbTableControl(PlcConfig plcConfig, PlcBlockDb plcBlockDb) {
            InitializeComponent();
            this.CurrentPlc = plcConfig;
            this.CurrentPlcBlockDb = plcBlockDb;
            this.Load += BlockDbTable_Load;
            input1.Text = @"数据类型：\int\string[20]\real\lreal\   占位eg:\Array[1..100] of Byte";
        }

        #region Props

        /// <summary>
        /// 当前点位列表集合
        /// </summary>
        public BindingList<ImportData> CurrentPointDatas { get; private set; } = new BindingList<ImportData>();

        /// <summary>
        /// 当前PLC信息
        /// </summary>
        public PlcConfig CurrentPlc { get; private set; } = default;

        /// <summary>
        /// 当前PLCDB块
        /// </summary>
        public PlcBlockDb CurrentPlcBlockDb { get; private set; } = default;

        /// <summary>
        /// 是否监视
        /// </summary>
        public bool IsWatch { get; set; } = false;




        #endregion


        #region Methods

        /// <summary>
        /// 初始化点位Table
        /// </summary>
        private void InitPointTable() {
            tbPoint.Columns = new ColumnCollection() {
                new ColumnCheck(nameof(ImportData.IsCheck)).SetAlign(),
                new Column(nameof(ImportData.Id), "ID").SetTree("Children").SetAlign(),
                new Column(nameof(ImportData.ParentId), "ParentID").SetAlign(),
                new Column(nameof(ImportData.Description), "名称").SetTree("SubItems").SetColAlign(),
                new Column(nameof(ImportData.DataType), "数据类型").SetAlign().SetStyle(new Table.CellStyleInfo() { BackColor = Color.FloralWhite, ForeColor = Color.Black } ),
                new Column(nameof(ImportData.BytePositionStr), "偏移量").SetAlign().SetStyle(new Table.CellStyleInfo() { BackColor = Color.FloralWhite, ForeColor = Color.Black } ),
                new Column(nameof(ImportData.WatchValue), "监视值").SetMaxWidth("80").SetEllipsis().SetAlign().SetStyle(new Table.CellStyleInfo() { BackColor = Color.Yellow, ForeColor = Color.Black } ),
                new Column(nameof(ImportData.EffectTypeCellText), "作用").SetAlign(),
                new Column(nameof(ImportData.ActionId), "动作编号").SetAlign(),
                new Column(nameof(ImportData.ActionKey), "动作Key").SetAlign(),
                new Column(nameof(ImportData.LinkActionId), "关联动作编号").SetAlign(),
                new Column(nameof(ImportData.DataId), "数据编号").SetAlign(),
                new Column(nameof(ImportData.LocationId), "位置/组").SetAlign(),
                new Column(nameof(ImportData.Remark), "备注").SetAligns(ColumnAlign.Left, ColumnAlign.Center).SetMaxWidth("200").SetEllipsis(),
                new Column(nameof(ImportData.WriteValue), "写入值").SetAlign(),
                new ColumnSwitch(nameof(ImportData.AutoWrite), "自动写"){
                    //支持点击回调
                    Call = (value, record, i_row, i_col) => {
                        //执行耗时操作
                        Thread.Sleep(200);
                        var data = record as ImportData;
                        if (data.ParseType.ToLower().Contains("array"))
                        {
                            return false;
                        }
                        if (value)
                        {
                            if(data.WriteValue.IsNullOrEmpty())
                            {
                                MessageError("写入值不能为空！");
                                return false;
                            }
                        }
                        return value;
                    }
                }.SetAlign(),
                new Column(nameof(ImportData.Operate), "操作").SetAlign().SetFixed(),
            };

            tbPoint.EditMode = TEditMode.None;
            tbPoint.Bordered = true;
            tbPoint.EmptyHeader = true;
            tbPoint.EnableHeaderResizing = false;
            tbPoint.Gap = 6;
            tbPoint.CellClick += TbPoint_CellClick;
            tbPoint.CellBeginEditInputStyle += TbPoint_CellBeginEditInputStyle;
            tbPoint.CellEditComplete += TbPoint_CellEditComplete;
            tbPoint.CellButtonClick += TbPoint_CellButtonClick;
            tbPoint.ExpandChanged += TbPoint_ExpandChanged;
            ChangePointTableColumnVisible();
        }

        /// <summary>
        /// 修改表格列显示
        /// </summary>
        public void ChangePointTableColumnVisible() {
            if (DesignMode)
                return;

            //监视状态显示 监视值 、写入值 两列
            foreach (var column in tbPoint.Columns) {
                if (ListenShowColumns.Contains(column.Key)) {
                    if (App.CurrentPlcClient != null && App.CurrentPlcClient.PlcSession.IsConnected)
                        column.Visible = true;
                    else
                        column.Visible = false;
                }
                if (ListenHideColumn.Contains(column.Key)) {
                    if (App.CurrentPlcClient != null && App.CurrentPlcClient.PlcSession.IsConnected)
                        column.Visible = false;
                    else
                        column.Visible = true;
                }
            }

            if (this.IsHandleCreated)
                this.Invoke(() => { panel1.Enabled = !IsWatch; });

        }


        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="data"></param>
        private void DeleteCheckNodes(ImportData data) {
            MesDbClient.Deleteable<CksPlcDataPosition>().Where(a => a.Id == data.Id).ExecuteCommand();
            if (data.SubItems != null && data.SubItems.Length > 0) {
                foreach (var item in data.SubItems) {
                    DeleteCheckNodes(item);
                }
            }
        }


        #endregion


        #region Events

        /// <summary>
        /// Load事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BlockDbTable_Load(object sender, EventArgs e) {
            if (DesignMode)
                return;

            string desc = CurrentPlcBlockDb.WriteFrom switch {
                1 => "写入方：PC",
                2 => "写入方：PLC",
                3 => "写入方：混合",
                _ => ""
            };

            lblDBText.Text = $"{desc}  数据块：{CurrentPlcBlockDb.BlockDb}  模块：{CurrentPlcBlockDb.ModuleCellText}  备注：{CurrentPlcBlockDb.Remark}";

            InitPointTable();

            LoadPointData();
        }

        /// <summary>
        /// 单元格点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TbPoint_CellClick(object sender, TableClickEventArgs e) {
            if (e.Button == MouseButtons.Left) {
                var columns = tbPoint.Columns.ToList().FindAll(a => a.Visible);
                var col = columns[e.ColumnIndex];
                if (IsWatch) {
                    switch (col.Key) {
                        //设置监视模式下可编辑列
                        case "Description":
                        case "AutoWrite":
                        case "WriteValue":
                        case "ActionId":
                        case "DataId":
                        case "LinkActionId":
                        case "LocationId":
                        case "Remark":
                            tbPoint.EnterEditMode(e.RowIndex, e.ColumnIndex);
                            break;
                    }
                } else {
                    switch (col.Key) {
                        //设置非监视模式下可编辑列
                        case "Id":
                        case "WriteFromCellText":
                        case "EffectTypeCellText":
                        case "BytePosition":
                        case "WatchValue":
                        case "BytePositionStr":
                        case "OrderNo":
                            break;
                        default:
                            tbPoint.EnterEditMode(e.RowIndex, e.ColumnIndex);
                            break;
                    }
                }

            } else if (e.Button == MouseButtons.Right) {
                var data = e.Record as ImportData;
                var index = CurrentPointDatas.IndexOf(data);
                var indexId = index + 1;
                if (index == -1 && data.ParentId == 0)
                    return;

                List<IContextMenuStripItem> menus = new List<IContextMenuStripItem>();
                if (CurrentPointDatas.Count == 0 || IsWatch) {
                    menus.Add(new ContextMenuStripItem("测试") { ID = "test", IconSvg = "SendOutlined", });
                } else {
                    menus.Add(new ContextMenuStripItem("上方插入1行") { ID = "add", IconSvg = "PlusCircleOutlined" });
                    menus.Add(new ContextMenuStripItem("删除当前行") { ID = "delete", IconSvg = "DeleteOutlined", Fore = Color.Red });
                }

                AntdUI.ContextMenuStrip.open(tbPoint, (menuItem) => {
                    var lst = ExpandPointDataToList(CurrentPointDatas);
                    var index = lst.IndexOf(data);
                    switch (menuItem.ID) {
                        case "add":
                            AddTableRows(lst, data);
                            break;
                        case "delete":
                            if (data.ParentId > 0) {
                                var sub = lst.Find(a => a.Id == data.ParentId);
                                var subs = sub.SubItems.ToList();
                                subs.Remove(data);
                                sub.SubItems = subs.ToArray();
                            }
                            CurrentPointDatas.Remove(data);
                            DeleteCheckNodes(data);
                            BtnSaveAll_Click(null, null);
                            break;
                        case "test":
                            //测试读取
                            TestReade();
                            break;
                        default:
                            break;
                    }
                    ReBindPointDatas(out List<ImportData> datas);

                }, menus.ToArray());
            }
        }

        /// <summary>
        /// 单元格编辑前事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TbPoint_CellBeginEditInputStyle(object sender, TableBeginEditInputStyleEventArgs e) {
            //选中全部文本
            e.Input.SelectAll();
        }

        /// <summary>
        /// 单元编辑完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TbPoint_CellEditComplete(object sender, EventArgs e) {
            //如果编辑的是数据类型发生了变化则需要重新计算偏移量
            if (e is ITableEventArgs tableEventArgs && tbPoint.Columns[tableEventArgs.ColumnIndex].Key == "DataType") {
                ReBindPointDatas(out List<ImportData> datas);
            }
        }

        /// <summary>
        /// 单元格按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TbPoint_CellButtonClick(object sender, TableButtonEventArgs e) {
            if (App.CurrentPlcClient == null)
                return;

            var one = e.Record as ImportData;
            var writeModel = one.Adapt<CksPlcDataPosition>();
            try {
                switch (e.Btn.Id) {
                    case "write"://写入
                        App.CurrentPlcClient.SetValue(writeModel, one.WriteValue);
                        break;
                    default:
                        break;
                }
            } catch (Exception ex) {
                MessageError(ex.Message);
            }
        }

        /// <summary>
        /// 新增行按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnAdd_Click(object sender, EventArgs e) {
            var lst = ExpandPointDataToList(CurrentPointDatas);
            AddTableRows(lst);
        }

        /// 导入DB按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDbImport_Click(object sender, EventArgs e) {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "(博图db块文件)|*.db";
            var dialog = ofd.ShowDialog();
            if (dialog == DialogResult.OK) {

                try {
                    var plcdb = CurrentPlcBlockDb;
                    //读取文件
                    string content = File.ReadAllText(ofd.FileName);
                    Regex regex = new Regex(@"(.+ : .+;[\s].+)|(.+ : .+;)|(.+ : Struct)|END_STRUCT;");
                    var matches = regex.Matches(content).ToList();

                    List<ImportData> ds = new List<ImportData>();
                    var parser = new S7CodeParser();
                    var eles = parser.Parse(content);
                    parser.ExpandCustomTypes(eles);
                    parser.FixIdsAndParentIds(eles);
                    var dataBlock = eles.Find(a => a.Type == "DATA_BLOCK").Children.Find(a => a.Type == "STRUCT");

                    BuildImportData(eles, dataBlock.Children, ds);

                    foreach (var item in ds) {
                        item.BlockDbId = plcdb.Id;
                        if (plcdb.WriteFrom <= 2)
                            item.WriteFrom = plcdb.WriteFrom;
                        else
                            item.WriteFrom = 2;
                    }

                    CurrentPointDatas.Clear();
                    CurrentPointDatas.AddRange(ds);

                    MesDbClient.Deleteable<CksPlcDataPosition>()
                     .Where(a => a.PlcId == CurrentPlc.Id && a.BlockDb == plcdb.BlockDb)
                     .ExecuteCommand();
                    BtnSaveAll_Click(null, null);
                } catch (Exception ex) {
                    MessageBoxShow("解析异常，请检查文件格式");
                }

            }
        }

        /// <summary>
        /// 保存全部按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnSaveAll_Click(object sender, EventArgs e) {
            if (CurrentPointDatas.Count <= 0)
                return;

            bool flag = ReBindPointDatas(out List<ImportData> datas);
            if (!flag) return;

            //遍历数据保存到数据块
            //自动为Struct分配LastID
            var lastParentID = 0;
            Dictionary<int, int> dicRealId = new Dictionary<int, int>();
            foreach (var point in datas) {
                var model = point.Adapt<CksPlcDataPosition>();
                model.BlockDbId = CurrentPlcBlockDb.Id;
                model.Module = CurrentPlcBlockDb.Module;
                model.BlockLength = CurrentPlcBlockDb.BlockLength;//修正每个点位的BlockLength长度
                if (model.Id == 0) {

                    if (model.ParseType.ToLower().Equals("struct")) {
                        if (dicRealId.ContainsKey(model.TempParentId)) {
                            model.ParentId = dicRealId[model.TempParentId];
                        }

                        //lastParentID = MesDbClient.Insertable(model).ExecuteReturnIdentity();
                        MesDbClient.Insertable(model).ExecuteReturnIdentity();

                        if (!dicRealId.ContainsKey(model.TempId)) {
                            dicRealId.Add(model.TempId, lastParentID);
                        }
                    } else {
                        if (dicRealId.ContainsKey(model.TempParentId))
                            model.ParentId = dicRealId[model.TempParentId];
                        MesDbClient.Insertable(model).ExecuteReturnIdentity();
                    }
                } else {
                    MesDbClient.Updateable(model).ExecuteCommand();
                }
            }

            var plcdb = CurrentPlcBlockDb;
            MesDbClient.Updateable(plcdb).ExecuteCommand();

            LoadPointData();

            MessageSuccess("保存成功");
        }

        /// <summary>
        /// 从数据库加载按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnLoadData_Click(object sender, EventArgs e) {
            LoadPointData();
        }

        /// <summary>
        /// 删除按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDeleteAll_Click(object sender, EventArgs e) {
            var selectRows = CurrentPointDatas.Where(o => o.IsCheck).ToList();
            if (selectRows.Count <= 0) {
                MessageWarn("请至少选择一行数据！");
                return;
            }
            //var result = MessageBoxWarn("确认要删除当前DB块的所有点位数据吗");
            var result = MessageBoxWarn("确认要删除当前DB块所选择的点位数据吗？");
            if (result == DialogResult.OK) {
                var plcdb = CurrentPlcBlockDb;
                MesDbClient.Deleteable<CksPlcDataPosition>()
                    .Where(a => selectRows.Select(b => b.Id).Contains(a.Id) && a.PlcId == CurrentPlc.Id && a.BlockDb == plcdb.BlockDb)
                    //.Where(a => a.PlcId == CurrentPlc.Id && a.BlockDb == plcdb.BlockDb)
                    .ExecuteCommand();
                LoadPointData();
                MessageSuccess("删除成功！");
            }
        }

        /// <summary>
        /// 表格展开状态改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TbPoint_ExpandChanged(object sender, TableExpandEventArgs e) {
            var item = e.Record as ImportData;
            if (e.Expand && IsArrayType(item.ParseType, out int arrayLenth, out string ParseType)) {
                var SubItems = new List<ImportData>();
                var size = GetTypeOffset(ParseType);
                var byteOffset = item.BytePosition;
                for (int j = 0; j < arrayLenth; j++) {

                    if (j != 0) {
                        byteOffset = size + byteOffset;
                    }

                    if (ParseType.ToLower() == "bool") {
                        string f1 = byteOffset.ToString("f1");
                        int end = f1.Substring(f1.IndexOf('.') + 1).ObjToInt();
                        if (end >= 8) //小数满8进1
                        {
                            byteOffset = ((int)byteOffset) + 1;
                        }
                    }

                    SubItems.Add(new ImportData {
                        Description = $"[{j + 1}]", //数组编号
                        OrderNo = j + 1,
                        BlockDb = item.BlockDb,
                        //ByteLength = size,
                        DataType = ParseType,
                        ParseType = ParseType,
                        BytePosition = byteOffset
                    });

                    item.SubItems = SubItems.ToArray();

                    if (ParseType != "char") {
                        item.Operate = null;
                    }
                }
            }
        }


        private void btnCopy_Click(object sender, EventArgs e) {

            DialogResult dialogResult = base.MessageBoxShow("确定要从模板中复制点位信息吗？");
            if (dialogResult == DialogResult.OK) {

                CurrentPointDatas.Clear();

                var list = MesDbClient.Queryable<CksPlcDataPositionTemp>()
               .ToList()
               .Adapt<List<ImportData>>()
               .ToList();

                list.ForEach((item) => {
                    item.Id = 0;
                    item.WriteFrom = CurrentPlcBlockDb.WriteFrom;
                    item.WorkStationCode = CurrentPlc.WorkstationCode;
                    item.PlcId = CurrentPlc.Id;
                    item.BlockDb = CurrentPlcBlockDb.BlockDb;
                    item.DataType = ConvertToS7Type(item);
                    CurrentPointDatas.Add(item);
                });

                //绑定到Table表格
                tbPoint.Binding(CurrentPointDatas);
            }

        }

        private void btnImportProcessData_Click(object sender, EventArgs e) {

            ImportProcessDataForm importProcessDataForm = new ImportProcessDataForm();
            var dialog = importProcessDataForm.ShowDialog();

            if (dialog == DialogResult.OK) {

                var list = new List<ImportData>();
                for (int i = 0; i < importProcessDataForm.Values.Count; i++) {
                    var item = importProcessDataForm.Values[i];

                    var row = new ImportData() {
                        WriteFrom = CurrentPlcBlockDb.WriteFrom,
                        WorkStationCode = CurrentPlc.WorkstationCode,
                        PlcId = CurrentPlc.Id,
                        BlockDb = CurrentPlcBlockDb.BlockDb,
                        ParentId = 0,
                        DataType = item.dataType.ToLower(),
                        Description = item.name,
                        Remark = item.desc,
                        LinkActionId = 901,
                        DataId = 90104 + i,
                    };
                    list.Add(row);
                }
                CurrentPointDatas.AddRange(list);
            }
         
        }

        #endregion



        private void TestReade() {
            try {
                string cmd = "DB3000.DBD2";
                var mds = cmd.Split('.');
                int db = int.Parse(mds[0].Replace("DB", ""));
                int startPos = int.Parse(Regex.Match(mds[1], "[0-9]+").Value);
                var dd = App.CurrentPlcClient.PlcSession.Read(S7.Net.DataType.DataBlock, db, startPos, S7.Net.VarType.Real, 1);
            } catch (Exception) {

            }
        }

        private void LoadPointData() {

            if (CurrentPlc == null) {
                return;
            }

            //CurrentPointDatas.Clear();

            var dataList = MesDbClient.Queryable<CksPlcDataPosition>()
                .Where(a => a.PlcId == CurrentPlc.Id && a.BlockDb == CurrentPlcBlockDb.BlockDb)
                .OrderBy(a => new { a.OrderNo }).ToList().Adapt<List<ImportData>>();

            int rowid = 0;
            dataList.ForEach(point => {
                rowid++;
                point.OrderNo = rowid;
                point.DataType = ConvertToS7Type(point);
            });

            var results = new List<ImportData>();
            //加载父子关系
            BuildTreeData(dataList, results);
            //赋值给当前点位数据集合
            CurrentPointDatas.Clear();
            CurrentPointDatas.AddRange(results);
            //重新绑定点位数据，计算偏移量
            ReBindPointDatas(out List<ImportData> datas);//查询数据

            //results = new List<ImportData>();
            //BuildTreeData(datas, results);
            //CurrentPointDatas.Clear();
            //CurrentPointDatas.AddRange(results);

            //绑定到Table表格
            tbPoint.Binding(CurrentPointDatas);
        }

        /// <summary>
        /// 构造树形结构
        /// </summary>
        /// <param name="AllDatas"></param>
        /// <param name="results"></param>
        /// <param name="parent"></param>
        private void BuildTreeData(List<ImportData> AllDatas, List<ImportData> results, ImportData parent = null) {

            int rootId = parent == null ? 0 : parent.Id;

            List<ImportData> childrens = new List<ImportData>();

            childrens = AllDatas.FindAll(a => a.ParentId == rootId);

            if (childrens.Count == 0) {
                return;
            }

            if (parent == null) {
                //如果是根节点则直接添加
                results.AddRange(childrens);
                foreach (var child in childrens) {
                    //查找子节点，存在子节点则添加
                    BuildTreeData(AllDatas, results, child);
                }

            } else {

                var childs = AllDatas.FindAll(a => a.ParentId == parent.Id);
                parent.SubItems = childs.ToArray();
                foreach (var child in parent.SubItems) {
                    BuildTreeData(AllDatas, results, child);
                }
            }

        }

        /// <summary>
        /// 添加新行
        /// </summary>
        /// <param name="all"></param>
        /// <param name="parentImportData"></param>
        private void AddTableRows(List<ImportData> all, ImportData parentImportData = null) {
            var pId = parentImportData == null ? 0 : parentImportData.ParentId;
            var row = new ImportData() {
                WriteFrom = CurrentPlcBlockDb.WriteFrom,
                WorkStationCode = CurrentPlc.WorkstationCode,
                PlcId = CurrentPlc.Id,
                BlockDb = CurrentPlcBlockDb.BlockDb,
                ParentId = pId,
                DataType = "Struct", //默认给个Int
            };

            if (CurrentPlcBlockDb.WriteFrom <= 2)
                row.WriteFrom = CurrentPlcBlockDb.WriteFrom;
            else
                row.WriteFrom = 2;

            if (parentImportData != null) {
                if (parentImportData.ParentId == 0) {
                    //根目录插入
                    var index = CurrentPointDatas.IndexOf(parentImportData);
                    CurrentPointDatas.Insert(index, row);
                } else {
                    //子目录插入
                    var parent = all.Find(a => a.Id == parentImportData.ParentId);
                    var subs = parent.SubItems.ToList();
                    var index = subs.IndexOf(parentImportData);
                    subs.Insert(index, row);
                    parent.SubItems = subs.ToArray();
                }

            } else {
                CurrentPointDatas.Add(row);
            }
        }

        /// <summary>
        /// 重新绑定点位数据，需要重新计算偏移值
        /// </summary>
        private bool ReBindPointDatas(out List<ImportData> lst) {
            lst = new List<ImportData>();
            try {

                //移除parentid不为0的 平铺到List，计算偏移，计算偏移时插入struct
                lst = ExpandPointDataToList(CurrentPointDatas);
                var plcdb = CurrentPlcBlockDb;
                var last = lst.LastOrDefault();

                if (last == null) {
                    return false;
                }

                if (string.IsNullOrEmpty(last.DataType)) {
                    throw new Exception($"{last.Id}数据类型不能为空");
                }

                for (int i = 0; i < lst.Count; i++) {
                    var item = lst[i];

                    item.OrderNo = i + 1;
                    if (string.IsNullOrEmpty(item.DataType)) {
                        throw new Exception($"{item.Id}数据类型不能为空");
                    }

                    var templenth = GetVariableOffset(item);

                    if (i == 0) { //如果是第一个节点则偏移为0

                        item.BytePosition = 0;

                    } else {  //如果不是第一个节点，则计算偏移

                        //获取上一个节点的偏移量
                        var prevItem = lst[i - 1];
                        var prevItemDataLenth = GetVariableOffset(prevItem);

                        //计算当前节点的偏移量
                        item.BytePosition = prevItem.BytePosition + prevItemDataLenth;

                        //如果当前类型是bool 小数满8进1
                        if (item.DataType.ToLower().Equals("bool")) {
                            //4.9 取小数部分
                            string f1 = item.BytePosition.ToString("f1");
                            int end = f1.Substring(f1.IndexOf('.') + 1).ObjToInt();
                            if (end >= 8) //小数满8进1
                            {
                                item.BytePosition = ((int)item.BytePosition) + 1;
                            }
                        }

                        //如果上一个是bool 但是当前不是bool类型 || 当前ParentID != 上个节点ParentID
                        if (prevItem.DataType.ToLower().Equals("bool")) {
                            if (!item.DataType.ToLower().Equals("bool") || item.ParentId != prevItem.ParentId)
                                item.BytePosition++;
                        }

                        if (IsArrayType(item.ParseType, out int arrayLenth, out string ParseType)) {
                            item.SubItems = new List<ImportData>() { new ImportData() { } }.ToArray();
                            if (ParseType != "char") {
                                item.Operate = null;
                            }
                        }
                    }

                    //计算完偏移需要修正一下偏移
                    //如果当前类型不是bool 也不是偶数
                    int offsetlen = (int)item.BytePosition;
                    if (!item.DataType.ToLower().Equals("bool")) {
                        if (offsetlen % 2 != 0)
                            offsetlen++;
                        item.BytePosition = offsetlen;
                    }
                    item.BlockDb = plcdb.BlockDb;
                    item.ByteLength = (int)templenth;
                    item.WorkStationCode = CurrentPlc.WorkstationCode;
                    item.PlcId = CurrentPlc.Id;

                }

                //遍历完成，如果最后是bool结尾进行+1操作
                int fixEnd = 0;
                if (last.DataType.ToLower().Equals("bool"))
                    fixEnd = 1;

                int blockLenth = (int)last.BytePosition + last.ByteLength + fixEnd;
                if (blockLenth % 2 != 0)
                    blockLenth++;

                tbPoint.Binding(CurrentPointDatas);

                //当前PLC数据块的长度
                CurrentPlcBlockDb.BlockLength = blockLenth;

                return true;

            } catch (Exception ex) {

                MessageError(ex.Message);
                return false;

            }
        }

        [Obsolete("", true)]
        private bool ReBindPointDataOld(out List<ImportData> lst) {
            lst = new List<ImportData>();
            try {
                Debug.WriteLine($"start time:{DateTime.Now.ToString()}");
                //移除parentid不为0的 平铺到List，计算偏移，计算偏移时插入struct
                lst = ExpandPointDataToList(CurrentPointDatas);

                var plcdb = CurrentPlcBlockDb;
                var last = lst.LastOrDefault();
                if (last == null)
                    return false;

                if (string.IsNullOrEmpty(last.DataType))
                    throw new Exception("数据类型不能为空");


                for (int i = 0; i < lst.Count; i++) {

                    var item = lst[i];
                    item.OrderNo = i + 1;
                    if (string.IsNullOrEmpty(item.DataType))
                        throw new Exception("数据类型不能为空");


                    if (item.OrderNo == 3) {
                    }
                    var templenth = GetVariableOffset(item);



                    if (i == 0) {
                        item.BytePosition = 0;

                    } else {
                        var lastItem = lst[i - 1];
                        var lastLenth = GetVariableOffset(lastItem);
                        item.BytePosition = lastItem.BytePosition + lastLenth;

                        //如果当前类型是bool 小数满8进1
                        if (item.DataType.ToLower().Equals("bool")) {
                            //4.9 取小数部分
                            string f1 = item.BytePosition.ToString("f1");
                            int end = f1.Substring(f1.IndexOf('.') + 1).ObjToInt();
                            if (end >= 8) //小数满8进1
                            {
                                item.BytePosition = ((int)item.BytePosition) + 1;
                            }
                        }
                        //如果上一个是bool 但是当前不是bool类型 || 当前ParentID != 上个节点ParentID
                        if (lastItem.DataType.ToLower().Equals("bool")) {
                            if (!item.DataType.ToLower().Equals("bool") || item.ParentId != lastItem.ParentId)
                                item.BytePosition++;
                        }

                    }

                    //计算完偏移需要修正一下偏移
                    //如果当前类型不是bool 也不是偶数

                    int offsetlen = (int)item.BytePosition;
                    if (!item.DataType.ToLower().Equals("bool")) {
                        if (offsetlen % 2 != 0)
                            offsetlen++;
                        item.BytePosition = offsetlen;
                    }
                    item.BlockDb = plcdb.BlockDb;


                    item.ByteLength = (int)templenth;

                    item.WorkStationCode = CurrentPlc.WorkstationCode;
                    item.PlcId = CurrentPlc.Id;
                }
                //遍历完成，如果最后是bool结尾进行+1操作
                int fixEnd = 0;
                if (last.DataType.ToLower().Equals("bool"))
                    fixEnd = 1;

                int blockLenth = (int)last.BytePosition + last.ByteLength + fixEnd;
                if (blockLenth % 2 != 0)
                    blockLenth++;

                foreach (var item in lst) {
                    item.BlockLength = blockLenth;

                    //如果是数组追加子元素
                    if (IsArrayType(item.ParseType, out int arrayLenth, out string ParseType)) {
                        var SubItems = new List<ImportData>();
                        var size = GetTypeOffset(ParseType);
                        var byteOffset = item.BytePosition;
                        for (int i = 0; i < arrayLenth; i++) {

                            if (i != 0)
                                byteOffset = size + byteOffset;
                            if (ParseType == "bool") {
                                string f1 = byteOffset.ToString("f1");
                                int end = f1.Substring(f1.IndexOf('.') + 1).ObjToInt();
                                if (end >= 8) //小数满8进1
                                {
                                    byteOffset = ((int)byteOffset) + 1;
                                }
                            }
                            SubItems.Add(new ImportData {
                                Description = $"[{i + 1}]", //数组编号
                                OrderNo = i + 1,
                                BlockDb = item.BlockDb,
                                // ByteLength = size,
                                DataType = ParseType,
                                ParseType = ParseType,
                                BytePosition = byteOffset
                            });
                        }
                        item.SubItems = SubItems.ToArray();
                        if (ParseType != "char")
                            item.Operate = null;

                    }
                }

                tbPoint.Binding(CurrentPointDatas);
                CurrentPlcBlockDb.BlockLength = blockLenth;
                return true;
            } catch (Exception ex) {
                MessageError(ex.Message);
                return false;
            } finally {
                Debug.WriteLine($"end time:{DateTime.Now.ToString()}");
            }
        }

        private void BuildImportData(List<Element> eles, List<Element> Children, List<ImportData> ds) {
            foreach (var item in Children) {

                ImportData data = new ImportData();
                data.Description = item.Name;
                data.DataType = item.Type;
                data.Remark = item.Comment;
                data.TempParentId = item.ParentId;
                data.TempId = item.Id;

                ds.Add(data);
                var udt = eles.Find(a => a.Type == "TYPE" && a.Name == item.Type);//自定义类型

                if (udt != null) { //用户自定义类型：

                    data.DataType = "STRUCT";

                }

                if (item.Children.Count > 0) {
                    BuildImportData(eles, item.Children, ds);
                }
            }
        }

       
    }
}
